#pragma once

#include <iostream>
#include <windows.h>
#include <ostream>

namespace yconsole
{
	enum Color
	{
		black = 0,
		blue = 1,
		green = 2,
		cyan = blue+green,
		red = 4,
		magenta = blue + red, 
		brown = green + red,
		lightgray = blue + green + red, 
		darkgray = 8,
		intensity = 8,
		lightblue = blue + intensity,
		lightgreen = green + intensity, 
		lightcyan = blue + green + intensity ,
		lightred = red + intensity, 
		lightmagenta = blue + red + intensity ,
		yellow = green + red + intensity ,
		white = blue + green + red + intensity ,

	};
	class ConsoleTextColor
	{

	private:
		HANDLE	m_stdout;
		CONSOLE_SCREEN_BUFFER_INFO		m_csbi;
		Color		m_fg;
		Color		m_bg;
	public:
		ConsoleTextColor() 
			: m_stdout(GetStdHandle( STD_OUTPUT_HANDLE ))		
		{
			GetConsoleScreenBufferInfo(m_stdout , &m_csbi );
		}

		~ConsoleTextColor()
		{
			SetConsoleTextAttribute( m_stdout, m_csbi.wAttributes );
		}

		void fg_color(Color color) 
		{
			m_fg = color;
			SetConsoleTextAttribute( m_stdout, (m_bg << 4) | color );
		}

		void bg_color(Color color) 
		{
			m_bg = color;
			SetConsoleTextAttribute( m_stdout, (color << 4) | m_fg );
		}

		static ConsoleTextColor&	getInstance()
		{
			static ConsoleTextColor _ins;
			return _ins;
		}

	};

#define DEC_OSTREAM_COLOR(color)	\
	inline std::ostream& fg_##color( std::ostream& os )	\
	{\
		ConsoleTextColor::getInstance().fg_color(color);\
		return os;\
	}\
	inline std::ostream& bg_##color( std::ostream& os )	\
	{\
		ConsoleTextColor::getInstance().bg_color(color);\
		return os;\
	}\
	inline std::wostream& fg_##color( std::wostream& os )	\
	{\
		ConsoleTextColor::getInstance().fg_color(color);\
		return os;\
	}\
	inline std::wostream& bg_##color( std::wostream& os )	\
	{\
		ConsoleTextColor::getInstance().bg_color(color);\
		return os;\
	}

	DEC_OSTREAM_COLOR(red)
	DEC_OSTREAM_COLOR(green)
	DEC_OSTREAM_COLOR(blue)
	DEC_OSTREAM_COLOR(white)
	DEC_OSTREAM_COLOR(cyan)
	DEC_OSTREAM_COLOR(magenta)
	DEC_OSTREAM_COLOR(yellow)
	DEC_OSTREAM_COLOR(black)
	DEC_OSTREAM_COLOR(brown)
	DEC_OSTREAM_COLOR(lightgray)
	DEC_OSTREAM_COLOR(darkgray)
	DEC_OSTREAM_COLOR(intensity)
	DEC_OSTREAM_COLOR(lightblue)
	DEC_OSTREAM_COLOR(lightgreen)
	DEC_OSTREAM_COLOR(lightcyan)
	DEC_OSTREAM_COLOR(lightred)
	DEC_OSTREAM_COLOR(lightmagenta)
}